package com.cq.hd.order.factory.orderSettle;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.entity.hf.HfTradeAccountPay;
import com.cq.hd.common.enums.biz.AgentEnterStateEnum;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeStateEnum;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeTypeEnum;
import com.cq.hd.common.utils.GenerateUtil;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.member.api.TbAgentEnterApplyApi;
import com.cq.hd.member.api.dto.AgentEnterApplyDetailDto;
import com.cq.hd.member.api.vo.AgentEnterApplyDetailVo;
import com.cq.hd.order.api.vo.OrderSettleBillVo;
import com.cq.hd.order.config.LockUtils;
import com.cq.hd.order.mapper.TbOrderSettleBillMapper;
import com.cq.hd.order.po.TbOrderSettleBillPo;
import com.cq.hd.system.api.HfApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

@Component
@Slf4j
public class CommissionOrderSettleBillHandler extends AbstractOrderSettleBillHandler {

    @Autowired
    private TbOrderSettleBillMapper orderSettleBillMapper;

    @Autowired
    private TbAgentEnterApplyApi agentEnterApplyApi;

    @Autowired
    private HfApi hfApi;

    @Override
    protected Integer getType() {
        return OrderSettleBillTradeTypeEnum.COMMISSION_AMT.getValue();
    }

    @Override
    public Boolean transactAmt(OrderSettleBillVo orderSettleBillVo) {
        Long id = orderSettleBillVo.getId();

        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "transactCommissionAmt:" + id);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            TbOrderSettleBillPo tbOrderSettleBillPo = orderSettleBillMapper.selectById(id);
            if (OrderSettleBillTradeStateEnum.SUCCESS.getValue().equals(tbOrderSettleBillPo.getTradeState())) {
                log.info("订单结算佣金已处理成功，orderSettleBillId：{}", id);
                return true;
            }

            // 查询经纪人入驻的列表，获取对应的落地会员号
            AgentEnterApplyDetailDto agentEnterApplyDetailDto = new AgentEnterApplyDetailDto();
            agentEnterApplyDetailDto.setState(AgentEnterStateEnum.SIGN_SUCCESS.getValue());
            agentEnterApplyDetailDto.setUserIds(Collections.singletonList(orderSettleBillVo.getAgentId()));
            List<AgentEnterApplyDetailVo> agentEnterApplyDetailVos = agentEnterApplyApi.listByDto(agentEnterApplyDetailDto).unpack();

            // 查询经纪人是否已签约成功，如果未签约，则记录到表，不调用hf接口
            if (!CollectionUtils.isEmpty(agentEnterApplyDetailVos)) {
                AgentEnterApplyDetailVo agentEnterApplyDetailVo = agentEnterApplyDetailVos.get(0);
                String inHfId = agentEnterApplyDetailVo.getHfId();
                String minorMemberId = agentEnterApplyDetailVo.getMinorMemberId();

                // 根据reqData和reqSeqId调用余额支付查询接口做查单，如果已经支付成功则修改状态=支付成功
                LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
                String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
                String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

                HfTradeAccountPay hfTradeAccountPay = new HfTradeAccountPay();
                hfTradeAccountPay.setReqDate(yyyyMMdd);
                hfTradeAccountPay.setReqSeqId(reqSeqId);
                hfTradeAccountPay.setOrgReqDate(orderSettleBillVo.getReqDate());
                hfTradeAccountPay.setOrgReqSeqId(orderSettleBillVo.getReqSeqId());
                JSONObject queryJSONObject = hfApi.tradeAccountAmtQuery(hfTradeAccountPay).unpack();
                if (queryJSONObject != null) {
                    JSONObject data = queryJSONObject.getJSONObject("data");
                    String respCode = data.getString("resp_code");
                    if ("00000000".equals(respCode)) {
                        // 交易状态 P:处理中；S：成功；F：失败
                        String transStat = data.getString("trans_stat");
                        String outHfId = queryJSONObject.getString("out_huifu_id");
                        JSONObject acctSplitBunch = queryJSONObject.getJSONObject("acct_split_bunch");

                        orderSettleBillVo.setInHfId(inHfId);
                        orderSettleBillVo.setOutHfId(outHfId);

                        if ("S".equals(transStat)) {
                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                        } else if ("P".equals(transStat)) {
                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                        } else if ("F".equals(transStat)) {
                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                            orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                        } else if ("C".equals(transStat)) {
                            JSONArray acctInfos = acctSplitBunch.getJSONArray("acct_infos");
                            if (acctInfos != null && acctInfos.size() > 0) {
                                JSONObject accInfoJsonObject = acctInfos.getJSONObject(0);
                                transStat = accInfoJsonObject.getString("trans_stat");
                                if ("S".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                                } else if ("P".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                                } else if ("F".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                                    orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                                }
                            }
                        } else {
                            orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                        }

                        // 如果失败，则重新调用余额支付税筹接口（给经纪人分佣金），并更新订单结算记录状态
                        if (OrderSettleBillTradeStateEnum.FAIL.getValue().equals(orderSettleBillVo.getTradeState())) {
                            // 如果是重新调用余额支付接口，则请求日期和请求流水号需要用最新的
                            orderSettleBillVo.setReqDate(yyyyMMdd);
                            orderSettleBillVo.setReqSeqId(reqSeqId);

                            hfTradeAccountPay = new HfTradeAccountPay();
                            hfTradeAccountPay.setReqDate(orderSettleBillVo.getReqDate());
                            hfTradeAccountPay.setReqSeqId(orderSettleBillVo.getReqSeqId());
                            hfTradeAccountPay.setInHfId(orderSettleBillVo.getInHfId());
                            hfTradeAccountPay.setGoodsDesc("给经纪人支付佣金");
                            hfTradeAccountPay.setTransAmt(orderSettleBillVo.getReceiveAmt().toString());
                            hfTradeAccountPay.setHycFlag("Y");
                            hfTradeAccountPay.setBmemberId(minorMemberId);
                            JSONObject jsonObject = hfApi.tradeAccountAmtPay(hfTradeAccountPay).unpack();
                            if (jsonObject != null) {
                                data = jsonObject.getJSONObject("data");
                                // 交易状态 P:处理中；S：成功；F：失败
                                transStat = data.getString("trans_stat");
                                outHfId = jsonObject.getString("out_huifu_id");
                                acctSplitBunch = jsonObject.getJSONObject("acct_split_bunch");

                                orderSettleBillVo.setInHfId(inHfId);
                                orderSettleBillVo.setOutHfId(outHfId);

                                if ("S".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                                } else if ("P".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                                } else if ("F".equals(transStat)) {
                                    orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                                    orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                                } else if ("C".equals(transStat)) {
                                    JSONArray acctInfos = acctSplitBunch.getJSONArray("acct_infos");
                                    if (acctInfos != null && acctInfos.size() > 0) {
                                        JSONObject accInfoJsonObject = acctInfos.getJSONObject(0);
                                        transStat = accInfoJsonObject.getString("trans_stat");
                                        if ("S".equals(transStat)) {
                                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                                        } else if ("P".equals(transStat)) {
                                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                                        } else if ("F".equals(transStat)) {
                                            orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                                            orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                                        }
                                    }
                                } else {
                                    orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                                }

                                // 在提现时必须要做查单处理
                                int update = orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);
                                if (update == 0) {
                                    log.error("更新订单结算佣金支付流水记录状态失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                                    return false;
                                }
                            }
                        } else {
                            // 在提现时必须要做查单处理
                            int update = orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);
                            if (update == 0) {
                                log.error("更新订单结算佣金支付流水记录状态失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                                return false;
                            }
                        }

                        return true;
                    }
                }

                orderSettleBillVo.setReqDate(yyyyMMdd);
                orderSettleBillVo.setReqSeqId(reqSeqId);

                hfTradeAccountPay = new HfTradeAccountPay();
                hfTradeAccountPay.setReqDate(orderSettleBillVo.getReqDate());
                hfTradeAccountPay.setReqSeqId(orderSettleBillVo.getReqSeqId());
                hfTradeAccountPay.setInHfId(orderSettleBillVo.getInHfId());
                hfTradeAccountPay.setGoodsDesc("给经纪人支付佣金");
                hfTradeAccountPay.setTransAmt(orderSettleBillVo.getReceiveAmt().toString());
                hfTradeAccountPay.setHycFlag("Y");
                hfTradeAccountPay.setBmemberId(minorMemberId);
                JSONObject jsonObject = hfApi.tradeAccountAmtPay(hfTradeAccountPay).unpack();
                if (jsonObject != null) {
                    JSONObject data = jsonObject.getJSONObject("data");
                    // 交易状态 P:处理中；S：成功；F：失败
                    String transStat = data.getString("trans_stat");
                    String outHfId = jsonObject.getString("out_huifu_id");
                    JSONObject acctSplitBunch = jsonObject.getJSONObject("acct_split_bunch");

                    orderSettleBillVo.setInHfId(inHfId);
                    orderSettleBillVo.setOutHfId(outHfId);

                    if ("S".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                    } else if ("P".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                    } else if ("F".equals(transStat)) {
                        orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                        orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                    } else if ("C".equals(transStat)) {
                        JSONArray acctInfos = acctSplitBunch.getJSONArray("acct_infos");
                        if (acctInfos != null && acctInfos.size() > 0) {
                            JSONObject accInfoJsonObject = acctInfos.getJSONObject(0);
                            transStat = accInfoJsonObject.getString("trans_stat");
                            if ("S".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.SUCCESS.getValue());
                            } else if ("P".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.PROCESSING.getValue());
                            } else if ("F".equals(transStat)) {
                                orderSettleBillVo.setTradeState(OrderSettleBillTradeStateEnum.FAIL.getValue());
                                orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                            }
                        }
                    } else {
                        orderSettleBillVo.setTradeFailReason(JSON.toJSONString(data));
                    }

                    // 在提现时必须要做查单处理
                    int update = orderSettleBillMapper.updateOrderSettleBill(orderSettleBillVo);
                    if (update == 0) {
                        log.error("更新订单结算佣金支付流水记录状态失败，orderSettleBillId：{}", orderSettleBillVo.getId());
                        return false;
                    }
                }
            }

            return true;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    @Override
    public Boolean transfer(OrderSettleBillVo orderSettleBillVo) {
        return null;
    }
}
